import Foundation

public struct TraceEvent: Codable {
    /// 事件名称
    public let event: String
    
    /// 事件负载数据
    public let payload: [String: Any]?
    
    /// 事件发生时间
    public let timestamp: TimeInterval
    
    /// 事件唯一ID
    public let eventId: String
    
    /// 事件所在页面
    public let page: String?
    
    /// 事件持续时间（毫秒）
    public let duration: Int?
    
    /// 公共参数
    public let commonParams: CommonParams
    
    public init(event: String, payload: [String: Any]? = nil, page: String? = nil, duration: Int? = nil) {
        self.event = event
        self.payload = payload
        self.page = page
        self.duration = duration
        self.timestamp = Date().timeIntervalSince1970
        self.eventId = UUID().uuidString
        self.commonParams = CommonParams()
    }
    
    enum CodingKeys: String, CodingKey {
        case event, payload, timestamp, eventId, page, duration, commonParams
    }
    
    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(event, forKey: .event)
        try container.encode(timestamp, forKey: .timestamp)
        try container.encode(eventId, forKey: .eventId)
        try container.encode(page, forKey: .page)
        try container.encode(duration, forKey: .duration)
        try container.encode(commonParams, forKey: .commonParams)
        
        if let payload = payload {
            let payloadData = try JSONSerialization.data(withJSONObject: payload, options: [])
            let payloadString = String(data: payloadData, encoding: .utf8)
            try container.encode(payloadString, forKey: .payload)
        }
    }
    
    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        event = try container.decode(String.self, forKey: .event)
        timestamp = try container.decode(TimeInterval.self, forKey: .timestamp)
        eventId = try container.decode(String.self, forKey: .eventId)
        page = try container.decodeIfPresent(String.self, forKey: .page)
        duration = try container.decodeIfPresent(Int.self, forKey: .duration)
        commonParams = try container.decode(CommonParams.self, forKey: .commonParams)
        
        if let payloadString = try container.decodeIfPresent(String.self, forKey: .payload),
           let payloadData = payloadString.data(using: .utf8),
           let payloadDict = try? JSONSerialization.jsonObject(with: payloadData, options: []) as? [String: Any] {
            payload = payloadDict
        } else {
            payload = nil
        }
    }
}

/// 公共参数
public struct CommonParams: Codable {
    /// 设备系统
    public let osType: String
    
    /// 系统版本
    public let osVersion: String
    
    /// 设备品牌
    public let deviceBrand: String
    
    /// 设备型号
    public let deviceModel: String
    
    /// 应用版本
    public let appVersion: String
    
    /// 应用构建版本
    public let appBuildVersion: String
    
    /// 渠道信息
    public let channel: String
    
    /// 用户ID
    public let userId: String?
    
    /// 设备ID
    public let deviceId: String
    
    /// 网络类型
    public let networkType: String
    
    /// 地理位置
    public let location: Location?
    
    public init() {
        self.osType = "iOS"
        self.osVersion = UIDevice.current.systemVersion
        self.deviceBrand = "Apple"
        self.deviceModel = TraceUtils.deviceModel()
        self.appVersion = TraceUtils.appVersion() ?? "Unknown"
        self.appBuildVersion = TraceUtils.appBuildVersion() ?? "Unknown"
        self.channel = TraceManager.shared.config.channel
        self.userId = TraceManager.shared.userId
        self.deviceId = TraceUtils.deviceId()
        self.networkType = TraceUtils.networkType()
        self.location = TraceManager.shared.location
    }
}

/// 地理位置
public struct Location: Codable {
    /// 经度
    public let longitude: Double
    
    /// 纬度
    public let latitude: Double
    
    /// 国家
    public let country: String?
    
    /// 省份
    public let province: String?
    
    /// 城市
    public let city: String?
    
    public init(longitude: Double, latitude: Double, country: String? = nil, province: String? = nil, city: String? = nil) {
        self.longitude = longitude
        self.latitude = latitude
        self.country = country
        self.province = province
        self.city = city
    }
}